home *** CD-ROM | disk | FTP | other *** search
/ SPACE 1 / SPACE - Library 1 - Volume 1.iso / program / 114 / xref2.bas < prev    next >
BASIC Source File  |  1987-10-17  |  18KB  |  566 lines

  1. Rem GFA Basic cross-referencer
  2. Rem ********** LEGAL NOTICE **********
  3. Rem Copyright (C) 1987 by Don Edwards
  4. Rem Permission is granted to distribute this program without charge
  5. Rem or for reasonable media charge only.
  6. Rem Permission is granted to put this program on any computer bulletin
  7. Rem board for downloading without charge or for normal access charges only.
  8. Rem
  9. Rem All other rights reserved
  10. Rem
  11. Rem "GFA-BASIC" may be a registered trademark owned by
  12. Rem Michtron, Inc (US) and/or GFA-Systemtechnik (Germany). It
  13. Rem is the name of a computer program written by GFA-Systemtechnik
  14. Rem and distributed in the US by Michtron, which program is covered
  15. Rem by US and foreign copyrights.
  16. Rem ********** END NOTICE **********
  17. Rem
  18. Rem What this program does:
  19. Rem
  20. Rem This program reads a GFA Basic program (Ascii save) and produces
  21. Rem two output files. The first is the listing with line numbers added;
  22. Rem the second is a list of variables and procedures, in alphabetic
  23. Rem order, with the line numbers of all references.
  24. Rem (It also uses 4 temporary files - RAMdisk STRONGLY recommended)
  25. Rem
  26. Rem main procedure
  27. Qqqinputread%=0
  28. Cls ! clear screen
  29. @Get_filenames
  30. @Examine_source
  31. @Sort_references
  32. @Combine_references
  33. @Format_report
  34. End
  35. Procedure Get_a_char
  36.   Rem This procedure provides a large buffer for character by
  37.   Rem character input. It also cooperates with the next procedure
  38.   Rem to allow quick input of the rest of the current line
  39.   Rem
  40.   If Qqqinputread%=0
  41.     Qqqinputread%=1
  42.     Qqqinputlen%=Lof(#1)
  43.     Qqqicurlen%=-1
  44.     Qqqinputpos%=0
  45.   Endif
  46.   If Qqqinputpos%>=Qqqicurlen%
  47.     Qqqicurlen%=Min(Max(1,Qqqinputlen%-1),10240)
  48.     Sub Qqqinputlen%,Qqqicurlen%
  49.     Qqqinputpos%=0
  50.     Qqqinputbuf$=Input$(Qqqicurlen%,#1)
  51.   Endif
  52.   Inc Qqqinputpos%
  53.   C$=Mid$(Qqqinputbuf$,Qqqinputpos%,1)
  54.   Cu$=Upper$(C$)
  55.   C%=Asc(C$)
  56.   Out #3,C%
  57. Return
  58. Procedure Finish_the_line
  59.   Rem this procedure causes the rest of the current line to be
  60.   Rem skipped over and passed to the numbered file, without examining
  61.   Rem each character separately.
  62.   Rem
  63.   Local X%
  64.   X%=Instr(Qqqinputpos%+1,Qqqinputbuf$,Chr$(13))
  65.   If X%>0
  66.     Dec X%
  67.     Print #3;Mid$(Qqqinputbuf$,Qqqinputpos%+1,X%-Qqqinputpos%);
  68.     Qqqinputpos%=X%
  69.     @Get_a_char
  70.   Else
  71.     Print #3;Mid$(Qqqinputbuf$,Qqqinputpos%+1);
  72.     Qqqinputpos%=Qqqicurlen%
  73.     @Get_a_char
  74.     If C%<>13
  75.       @Finish_the_line
  76.     Endif
  77.   Endif
  78. Return
  79. Procedure Examine_source
  80.   Rem
  81.   Rem this code reads the .LST file and produces a list of (line#, var)
  82.   Rem in a temporary file. (Note: "var" is anything that looks like a word
  83.   Rem but is not a Basic keyword; it includes procedure names, function
  84.   Rem names, and labels as well as variables)
  85.   Rem
  86.   Open "I",#1,Lst$
  87.   Open "O",#2,Tempfile1$
  88.   Open "O",#3,Lnm$
  89.   Lnum%=1
  90.   Print #3,Using "#### ",Lnum%;
  91.   Print "Reading Line ";
  92.   Lnox%=Crscol
  93.   Lnoy%=Crslin
  94.   Print Lnum%;
  95.   @Get_a_char
  96.   Rem
  97.   Rem in the following loop, C% contains the ascii code of the next char
  98.   Rem C$ contains the character
  99.   Rem Cu$ contains the uppercase version of the character
  100.   Rem these must ALWAYS be true at the beginning of a pass thru the loop
  101.   Rem
  102.   Repeat
  103.     If Cu$>="A" And Cu$<="Z" ! start of a word
  104.       Word$=C$ ! begin saving the word
  105.       If Not Eof(#1)
  106.         @Get_a_char ! get the next character
  107.         Do
  108.           Let Exit!=False
  109.           If (C$>="0" And C$<="9") Or (Cu$>="A" And Cu$<="Z") Or C$="_" Or C$="."
  110.             Word$=Word$+C$ ! add a letter, digit, underscore, dot
  111.           Else
  112.             If C$="$" Or C$="%" Or C$="!" Or C$=":" Or C$="?"
  113.               Word$=Word$+C$ ! add type char & terminate
  114.               @Get_a_char ! get the next character
  115.               Let Exit!=True
  116.             Else ! character not part of a word
  117.               Let Exit!=True
  118.             Endif
  119.           Endif
  120.           Exit If Eof(#1) Or Exit!
  121.           @Get_a_char ! if staying, get the next character
  122.         Loop
  123.       Endif
  124.       @Deal_with_word
  125.     Else ! not a word
  126.       If C%=13 ! carriage return
  127.         Inc Lnum% ! increment line counter
  128.         If Not Eof(#1)
  129.           @Get_a_char ! discard linefeed
  130.           If Not Eof(#1) ! there is a next line
  131.             Print #3,Using "#### ",Lnum%; ! numbered file
  132.             Print At(Lnox%,Lnoy%);Lnum%
  133.             @Get_a_char ! get 1st char of new line
  134.           Endif
  135.         Endif
  136.       Else ! not word, carriage return
  137.         If (C$>="0" And C$<="9") Or C$="&" ! numbers
  138.           Do ! skip the number
  139.             Exit If Eof(#1)
  140.             @Get_a_char
  141.             Exit If Not ((C$>="0" And C$<="9") Or (C$>="A" And C$<"G") Or C$="H" Or C$="X" Or C$="O" Or C$=".")
  142.           Loop
  143.         Else ! not word, carriage return, number
  144.           If C%=34 ! double quotes
  145.             Repeat ! skip the quoted string
  146.               Exit If Eof(#1) ! if file ends, stop
  147.               @Get_a_char
  148.             Until C%=34 Or C%=13 ! until matching quote or end of line
  149.             If C%=34 ! skip closing quote
  150.               @Get_a_char
  151.             Endif
  152.           Else ! not word, carriage return, number, quoted string
  153.             If C$="!" ! on-the-line comment
  154.               @Finish_the_line
  155.             Else ! don't know what it is - ignore it
  156.               @Get_a_char
  157.             Endif
  158.           Endif
  159.         Endif
  160.       Endif
  161.     Endif
  162.   Until Eof(#1)
  163.   Close #1
  164.   Close #2
  165.   Close #3
  166. Return
  167. Procedure Deal_with_word
  168.   Rem
  169.   Rem this routine takes the word in Word$ and tries to find what it is.
  170.   Rem if it's REM or DATA, the rest of the line is skipped
  171.   Rem otherwise, we look through a list of basic keywords - if we find
  172.   Rem the word, we're done.
  173.   Rem failing that, we write a line to file 2 consisting of the line#
  174.   Rem (in lnum) and the word
  175.   Rem
  176.   Local Lo%,Hi%,Mid%
  177.   Uword$=Upper$(Word$) ! uppercase for faster comparisons
  178.   If Not Word_list_read! ! first time thru - build the word list
  179.     @Read_word_list
  180.   Endif
  181.   If Uword$="REM" Or Uword$="DATA"
  182.     @Finish_the_line
  183.   Else ! do a binary search on the word list
  184.     Lo%=0 ! slot 0 unused
  185.     Hi%=Word_list_limit% ! this slot "//", not a valid word
  186.     Rem word, if present, is between lo% and hi%, exclusive at both ends
  187.     Do
  188.       Mid%=(Lo%+Hi%)/2 ! find midpoint
  189.       Exit If Mid%=Lo% ! implies nothing between lo% and hi%
  190.       Found!=(Hold_word_list$(Mid%)=Uword$) ! is midpoint the word?
  191.       Exit If Found!
  192.       If Hold_word_list$(Mid%)<Uword$ ! nope... if too low in list
  193.         Lo%=Mid% ! move lo% up
  194.       Else ! must be too high in list
  195.         Hi%=Mid% ! move hi% down
  196.       Endif
  197.     Loop
  198.     If Not Found!
  199.       Print #2,Lnum%;",";Word$
  200.     Endif
  201.   Endif
  202. Return
  203. Procedure Read_word_list
  204.   Rem
  205.   Rem build the word list in an array, doing sequence checking
  206.   Rem so that binary search may go unimpeded.
  207.   Rem
  208.   Word_list_read!=True ! we've been here now
  209.   Dim Hold_word_list$(300) ! the list
  210.   Word_list_limit%=0 ! unused slot
  211.   Do
  212.     Inc Word_list_limit% ! move to next slot
  213.     Read Hold_word_list$(Word_list_limit%) ! read the word
  214.     Exit If Hold_word_list$(Word_list_limit%)="//" ! special end marker
  215.     If Hold_word_list$(Word_list_limit%)<=Hold_word_list$(Word_list_limit%-1)
  216.       Print "words out of sequence ->";
  217.       Print Hold_word_list$(Word_list_limit%-1);", ";
  218.       Print Hold_word_list$(Word_list_limit%)
  219.       Stop ! sequence error must be fixed
  220.     Endif
  221.   Loop
  222. Return ! now the words follow
  223. Data ABS,ADD,ALERT,AND,ARRAYFILL,ARRPTR,AS,ASC,AT,ATN
  224. Data BASE,BGET,BIN$,BITBLT,BLOAD,BMOVE,BOX,BPUT,BREAK,BSAVE
  225. Data C:,CALL,CHAIN,CHDIR,CHDRIVE,CHR$,CIRCLE,CLEAR,CLEARW,CLOSE,CLOSEW
  226. Data CLR,CLS,COLOR,COS,CRSCOL,CRSLIN,CVD,CVF,CVI,CVL,CVS
  227. Data DATE$,DEC,DEFFILL,DEFFN,DEFLINE,DEFLIST,DEFMARK,DEFMOUSE,DEFNUM,DEFTEXT
  228. Data DFREE,DIM,DIM?,DIR,DIR$,DIV,DO,DOWNTO,DPEEK,DPOKE,DRAW
  229. Data EDIT,ELLIPSE,ELSE,END,ENDIF,EOF,EQV,ERASE,ERR,ERROR,EVEN,EXEC,EXIST
  230. Data EXIT,EXP
  231. Data FALSE,FATAL,FIELD,FILES,FILESELECT,FILL,FIX,FOR,FORM,FRAC,FRE,FULLW
  232. Data GET,GOSUB,GOTO,GRAPHMODE
  233. Data HARDCOPY,HEX$,HIDEM,HIMEM
  234. Data IF,IMP,INC,INFOW,INKEY$,INP,INP?,INPUT,INPUT$,INSTR,INT
  235. Data KILL
  236. Data LEFT$,LEN,LET,LINE,LIST,LLIST,LOAD,LOC,LOCAL,LOF,LOG,LOG10,LOOP,LPEEK
  237. Data LPOKE,LPOS,LPRINT,LSET
  238. Data MAX,MENU,MID$,MIN,MKD$,MKDIR,MKF$,MKI$,MKL$,MKS$,MOD,MONITOR,MOUSE,MOUSEK
  239. Data MOUSEX,MOUSEY,MUL
  240. Data NAME,NEW,NEXT,NOT
  241. Data OCT$,ODD,ON,OPEN,OPENW,OPTION,OR,OUT,OUT?
  242. Data PAUSE,PBOX,PCIRCLE,PEEK,PELLIPSE,PLOT,POINT,POKE,POLYFILL,POLYLINE
  243. Data POLYMARK,POS,PRBOX,PRINT,PROCEDURE,PSAVE,PUT
  244. Data QUIT
  245. Data RANDOM,RBOX,READ,RELSEEK,REPEAT,RESERVE,RESTORE,RESUME,RETURN,RIGHT$
  246. Data RMDIR,RND
  247. Data SAVE,SDPOKE,SEEK,SETCOLOR,SETTIME,SGET,SGN,SHOWM,SIN,SLPOKE,SOUND
  248. Data SPACE$,SPC,SPOKE,SPRITE,SPUT,SQR,STOP,STR$,STRING$,SUB,SWAP,SYSTEM
  249. Data TAB,TAN,TEXT,TIME$,TIMER,TITLEW,TO,TROFF,TRON,TRUE,TRUNC,TYPE
  250. Data UNTIL,UPPER$,USING
  251. Data VAL,VAL?,VARPTR,VOID,VSYNC
  252. Data WAVE,WEND,WHILE,WRITE
  253. Data XOR
  254. Data //,end of basic keyword list
  255. Procedure Get_filenames
  256.   Rem
  257.   Rem this routine gets all the filenames needed for this program
  258.   Rem
  259.   Print "Select Ascii-saved Basic program"
  260.   A$="A:\*.LST"
  261.   B$=""
  262.   Ok!=False
  263.   Repeat
  264.     Fileselect A$,B$,Lst$
  265.     If Lst$=""
  266.       End
  267.     Endif
  268.     If Exist(Lst$)
  269.       Ok!=True
  270.     Else
  271.       Print "(doesn't exist, try again)"
  272.     Endif
  273.     @Take_filename_apart(Lst$,*A$,*B$)
  274.   Until Ok!
  275.   Cls ! clear screen again
  276.   Ok!=False
  277.   Print Lst$
  278.   X%=Instr(B$,".")
  279.   If X%=0
  280.     B$=B$+".lnm"
  281.   Else
  282.     B$=Left$(B$,X%)+"lnm"
  283.   Endif
  284.   A$=A$+"*.LNM"
  285.   Print "Select numbered-program file"
  286.   Fileselect A$,B$,Lnm$
  287.   If Lnm$=""
  288.     End
  289.   Endif
  290.   Cls
  291.   Print Lst$;"   ";
  292.   Print Lnm$
  293.   @Take_filename_apart(Lnm$,*A$,*B$)
  294.   Y%=Instr(B$,".")
  295.   If Y%=0
  296.     B$=B$+".xrf"
  297.   Else
  298.     B$=Left$(B$,Y%)+"xrf"
  299.   Endif
  300.   A$=A$+"*.xrf"
  301.   Print "Select xref file"
  302.   Fileselect A$,B$,Xrf$
  303.   If Xrf$=""
  304.     End
  305.   Endif
  306.   Cls
  307.   Print Lst$;"   ";
  308.   Print Lnm$;"   ";
  309.   Print Xrf$
  310.   Print "Select DRIVE for temp files (filename doesn't matter)"
  311.   @Take_filename_apart(Xrf$,*A$,*B$)
  312.   Fileselect A$," ",Junk$
  313.   @Take_filename_apart(Junk$,*Tdrive$,*A$)
  314.   Rem out of that, only drive$ matters
  315.   Print "Selecting temp files ";
  316.   Repeat
  317.     Tempfile1$=Tdrive$+"F1"+Str$(Random(10000))
  318.   Until Not Exist(Tempfile1$)
  319.   Repeat
  320.     Tempfile2$=Tdrive$+"F2"+Str$(Random(10000))
  321.   Until Not Exist(Tempfile2$)
  322.   Repeat
  323.     Tempfile3$=Tdrive$+"F3"+Str$(Random(10000))
  324.   Until Not Exist(Tempfile3$)
  325.   Repeat
  326.     Tempfile4$=Tdrive$+"F4"+Str$(Random(10000))
  327.   Until Not Exist(Tempfile4$)
  328.   Print Tempfile1$;" ";Tempfile2$;" ";Tempfile3$;" ";Tempfile4$
  329. Return
  330. Procedure Take_filename_apart(Pathname$,P.path%,P.name%)
  331.   Rem
  332.   Rem this routine examines the filename (with path) in pathname$
  333.   Rem the path (up to final \) will be put in p.path
  334.   Rem the filename only will be put in p.name
  335.   Rem
  336.   Local X%,Y%
  337.   X%=Instr(Pathname$,":")
  338.   Repeat
  339.     Y%=X%
  340.     X%=Max(Instr(Y%+1,Pathname$,"\"),Instr(Y%+1,Pathname$,"/"))
  341.   Until X%=0
  342.   If Y%=0
  343.     *P.path%=Dir$
  344.     *P.name%=Pathname$
  345.   Else
  346.     *P.path%=Left$(Pathname$,Y%)
  347.     *P.name%=Mid$(Pathname$,Y%+1)
  348.   Endif
  349. Return
  350. Procedure Deletef
  351.   Rem
  352.   Rem this is a utility routine, it deletes all the temp files this
  353.   Rem program has left laying around.
  354.   Rem
  355.   Rem notes: (1) it assumes files are in the root of drive P:, my ramdisk
  356.   Rem        (2) it is dangerous - can easily delete too much
  357.   Rem
  358.   While Exist("p:f*")
  359.     Kill "p:f*"
  360.   Wend
  361. Return
  362. Procedure Sort_references
  363.   Rem
  364.   Rem this routine does some overhead for a merge sort of the disk file
  365.   Rem containing the list of references
  366.   Rem
  367.   Print "sorting - pass ";
  368.   Lnox%=Crscol
  369.   Lnoy%=Crslin
  370.   Pass%=0
  371.   Qqqinputbuf$="" ! to free memory
  372.   Void Fre(0)
  373.   Open "O",#1,Tempfile2$ ! create null file
  374.   Close #1 ! done with it
  375.   Repeat
  376.     @Sort_one_pass
  377.   Until Not Side2!
  378.   Kill Tempfile2$
  379.   Kill Tempfile3$
  380.   Kill Tempfile4$
  381. Return
  382. Procedure Sort_one_pass
  383.   Rem
  384.   Rem this routine does one pass of a merge sort
  385.   Rem at present it's strictly a two-by merge.
  386.   Rem
  387.   Inc Pass% ! print pass# so user doesn't get too impatient
  388.   Print At(Lnox%,Lnoy%);Pass%
  389.   Rcnt%=0 ! initialize record and segment counters
  390.   Seg%=1
  391.   Open "I",#1,Tempfile1$ ! open files
  392.   Open "I",#2,Tempfile2$
  393.   Open "O",#3,Tempfile3$
  394.   Open "O",#4,Tempfile4$
  395.   Side2!=False ! haven't used the second output file yet
  396.   Ofile!=False ! switch for which output file to use
  397.   F1oc!=False ! input record buffers not occupied
  398.   F2oc!=False
  399.   Old$="" ! no previous record
  400.   Oldr=0
  401.   Repeat
  402.     If Not F1oc! ! should fill buffer 1, preferably from input 1
  403.       On Error Gosub Errone
  404.       If Not Eof(#1)
  405.         Input #1,Ref1,Var1$ ! read the record
  406.         Inc Rcnt% ! count it
  407.         F1oc!=True ! buffer now occupied
  408.       Else ! have to read from input 2 instead
  409.         If Not Eof(#2) ! if we can
  410.           Input #2,Ref1,Var1$ ! read the record
  411.           Inc Rcnt% ! count it
  412.           F1oc!=True ! buffer occupied
  413.         Endif
  414.       Endif
  415.     Endif
  416.     Eofone:
  417.     If Not F2oc! ! should fill buffer 2 - see above
  418.       On Error Gosub Errtwo
  419.       If Not Eof(#2)
  420.         Input #2,Ref2,Var2$
  421.         Inc Rcnt%
  422.         F2oc!=True
  423.       Else
  424.         If Not Eof(#1)
  425.           Input #1,Ref2,Var2$
  426.           Inc Rcnt%
  427.           F2oc!=True
  428.         Endif
  429.       Endif
  430.     Endif
  431.     Eoftwo:
  432.     On Error ! normal error handling
  433.     If ((Var1$<Old$ Or (Var1$=Old$ And Ref1<Oldr)) Or Not F1oc!) And ((Var2$<Old$ Or (Var2$=Old$ And Ref2<Oldr)) Or Not F2oc!)
  434.       Rem have completed a "run", must switch output files
  435.       Ofile!=Not Ofile! ! switch the indicator
  436.       Inc Seg% ! count the next run
  437.       Oldr=0 ! no previous record in the run
  438.       Old$=""
  439.     Endif
  440.     If F1oc! And (Var1$>Old$ Or (Var1$=Old$ And Ref1>=Oldr)) And ((Var1$<Var2$ Or (Var1$=Var2$ And Ref1<=Ref2)) Or (Not F2oc!) Or (Var2$<Old$ Or (Var2$=Old$ And Ref2<Oldr)))
  441.       Rem should write record in buffer 1
  442.       @Sort_out(Ref1,Var1$) ! call routine to write it
  443.       F1oc!=False ! now the buffer's empty
  444.     Else
  445.       If F2oc! And (Var2$>Old$ Or (Var2$=Old$ And Ref2>=Oldr)) And ((Var2$<Var1$ Or (Var2$=Var1$ And Ref2<=Ref1)) Or (Not F1oc!) Or (Var1$<Old$ Or (Var1$=Old$ And Ref1<Oldr)))
  446.         Rem should write record in buffer 2
  447.         @Sort_out(Ref2,Var2$) ! call routine to write it
  448.         F2oc!=False ! now the buffer's empty
  449.         Rem if both buffers are occupied or both files are at eof, should always
  450.         Rem be writing one of the two buffers out.
  451.       Endif
  452.     Endif
  453.   Until Eof(#1) And Eof(#2) And Not (F1oc! Or F2oc!)
  454.   Close #1 ! close all the files
  455.   Close #2
  456.   Close #3
  457.   Close #4
  458.   Swap Tempfile1$,Tempfile3$ ! ready for next pass
  459.   Swap Tempfile2$,Tempfile4$ ! files 1&2 always input, 3&4 always output
  460.   Print "last pass had ";Rcnt%;" records in ";Seg%;" segments"," "
  461. Return
  462. Procedure Sort_out(X,Y$)
  463.   Rem
  464.   Rem output a record to the sort output file
  465.   Rem
  466.   Old$=Y$ ! save "previous-record" stuff for future use
  467.   Oldr=X
  468.   If Ofile! ! pick which file to write to
  469.     Side2!=True ! at least two runs, we'll need another pass
  470.     Print #4;X;",";Y$ ! write to file 4
  471.   Else
  472.     Print #3;X;",";Y$ ! write to file 3
  473.   Endif
  474. Return
  475. Rem
  476. Rem error (eof) routines for the above sort follow.
  477. Procedure Errone
  478.   Resume Eofone
  479. Return
  480. Procedure Errtwo
  481.   Resume Eoftwo
  482. Return
  483. Rem
  484. Procedure Errthree
  485.   Rem
  486.   Rem this special eof routine provides a dummy value for the
  487.   Rem combine logic in the next procedure
  488.   Rem
  489.   Var2$="//"
  490.   Resume Next
  491. Return
  492. Procedure Combine_references
  493.   Rem
  494.   Rem this routine reads the sorted references file
  495.   Rem and produces one record for each different variable.
  496.   Rem
  497.   Print "combining..."
  498.   Open "I",#1,Tempfile1$ ! open files
  499.   Open "O",#2,Tempfile2$
  500.   Input #1,Ref1$,Var1$ ! read the first record
  501.   Var2$="" ! clear to start the loop
  502.   While Var2$<>"//" ! watching for special eof marker
  503.     On Error Gosub Errthree ! provide for it
  504.     Input #1,Ref2$,Var2$ ! get the next record
  505.     On Error ! back to standard error handling
  506.     If Var2$=Var1$ ! if same variable
  507.       Ref1$=Ref1$+" "+Ref2$ ! combine the reference lists
  508.     Else ! not the same variable
  509.       Print #2;Ref1$;",";Var1$ ! write the "old" variable & list
  510.       Ref1$=Ref2$ ! start on the new one
  511.       Var1$=Var2$
  512.     Endif
  513.   Wend ! and go on
  514.   Close #1 ! close files
  515.   Close #2
  516.   Swap Tempfile1$,Tempfile2$ ! still want #1 to be input
  517.   Kill Tempfile2$ ! get rid of unneeded file
  518. Return
  519. Procedure Format_report
  520.   Rem
  521.   Rem this routine reads the combined file to produce the actual
  522.   Rem cross-reference report
  523.   Rem
  524.   Print "formatting report"
  525.   Open "I",#1,Tempfile1$ ! open files
  526.   Open "O",#2,Xrf$
  527.   On Error Gosub Errfour ! protect eof
  528.   Namform$="\"+Space$(18)+"\ " ! formats for print using
  529.   Numform$="#### "
  530.   While Not Eof(#1) ! thru the file
  531.     Input #1,Ref1$,Var1$ ! read a record
  532.     St%=1 ! starting position in ref1$
  533.     Cl%=0 ! starting position on line
  534.     While St%<Len(Ref1$) ! until done with references
  535.       If Cl%>56 ! line is full
  536.         Print #2 ! end the line
  537.         Cl%=0 ! ready for a new line
  538.       Endif
  539.       If Cl%=0 ! if at beginning of line
  540.         Print #2,Using Namform$,Var1$; ! print the variable name
  541.         Cl%=Cl%+Len(Namform$) ! move ahead in line
  542.         Var1$="" ! but only print name once per variable
  543.       Endif
  544.       En%=Instr(St%,Ref1$," ") ! find the end of the next line#
  545.       If En%=0 ! if there isn't a space,
  546.         En%=Len(Ref1$) ! use the rest of the references
  547.       Endif
  548.       Ll%=En%-St%+1 ! how many characters?
  549.       Print #2,Using Numform$,Val(Mid$(Ref1$,St%,Ll%)); ! print the number
  550.       Cl%=Cl%+Len(Numform$) ! move ahead in line
  551.       St%=En%+1 ! move to next reference
  552.     Wend
  553.     Print #2 ! end of a variable - end the line
  554.   Wend
  555.   Eoffour: ! also come here indirectly on eof
  556.   Close #1 ! close files
  557.   Close #2
  558.   Kill Tempfile1$ ! get rid of temporaries
  559. Return
  560. Procedure Errfour
  561.   Rem
  562.   Rem special eof routine for the final reporting phase
  563.   Rem
  564.   Resume Eoffour
  565. Return
  566.